package megalopolis.client;

import java.io.IOException;
import java.net.Socket;
import java.util.Set;

import megalopolis.common.Config;
import megalopolis.model.GameObject;
import megalopolis.model.Man;
import megalopolis.net.requests.LoginRequest;
import megalopolis.net.requests.MoveRequest;
import megalopolis.net.responses.LoginResponse;

/**
 * User: Kirill
 * Date: 19.02.2008
 */
public class Controller {

	private Config config;

	private ResponseHandler responseHandler;

	private NetworkHandler network;

	private KeysDefinition keys;

	private GameMap gameMap;

	private View view;

	private Man playerMan;

	public Controller(Config config) {
		this.config = config;
		gameMap = new GameMap();
		responseHandler = new ResponseHandler(this);
		keys = new KeysDefinition();
		keys.configureKeys(config);
		gameMap = new GameMap();
	}

	public void keyPressed(int keyCode) {
		if (keyCode == keys.key_forward) {
			move(MoveRequest.Movement.FORWARD);
		} else if (keyCode == keys.key_backward) {
			move(MoveRequest.Movement.BACKWARD);
		} else if (keyCode == keys.key_left) {
			move(MoveRequest.Movement.LEFT);
		} else if (keyCode == keys.key_right) {
			move(MoveRequest.Movement.RIGHT);
		}
	}

	private void move(MoveRequest.Movement movement) {
		network.sendRequest(new MoveRequest(movement));
	}

	public void setView(View view) {
		this.view = view;
	}

	public boolean login(String login, String password) throws IOException {
		// create connection to server
		Socket socket = new Socket(config.getString("server.host"), config.getInt("server.port"));

		// create network
		NetworkHandler network = new NetworkHandler(socket, responseHandler);

		// send login request in sync mode
		LoginResponse response = (LoginResponse) network.sendSyncRequest(new LoginRequest(login, password));

		if (response.isLogined()) {
			this.network = network;

			// start network handler
			network.start();

			return true;
		}

		return false;
	}

	public void reportException(Exception e) {
		e.printStackTrace();
	}

	public void exit() {
		if (network != null) {
			network.stop();
		}
		System.exit(0);
	}

	public void applyObjects(Set<GameObject> gameObjects) {
		gameMap.applyObjects(gameObjects);
		view.updateMap();
	}

	public GameMap getGameMap() {
		return gameMap;
	}

	public Man getPlayerMan() {
		return playerMan;
	}

	public void setPlayerMan(Man playerMan) {
		this.playerMan = playerMan;
	}

	public boolean isLogined() {
		return network != null;
	}
}
